#include "../../Socket/Connection.hpp"
#include "../../base/Defind.hpp"
#include "../../Socket/Reactor.hpp"
#include "../../Socket/Dispatch.hpp"
#include "../../base/BaseLog.hpp"
#include "../../base/Signal.hpp"
#include "../../base/ThreadPool.hpp"
#include <cstdlib>
#include <functional>
#include <iostream>
#include <string>
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>
#include <csignal>

static std::function<void(void)> ending;

void sig_int(int sig_) {
    char format[] = "dbserver exit!\n";
    info(format);
    ending();
}

int main(int argc, const char** argv) {
    if (argc < 2) 
    {
        std::cerr << "param invail\n";
        exit(1);
    }

    {
        using DBServer::Base::ThreadPool;
        ThreadPool::GetInstance()->work();

        using DBServer::Base::Signaler;
        std::unordered_map<signal_t, void (*)(int)> sig_cb_map;
        sig_cb_map[SIGINT] = sig_int;
        Signaler::GetInstance()->init(sig_cb_map);

        using namespace DBServer::Socket;
        Listener listener;
        listener.set_socket_info(argv[1], atoi(argv[2]));
        listener.create_socket();

        Dispatch dispatch(listener);

        ending = [&dispatch](){
            dispatch.stop();
        };

        std::vector<Reactor*> reactors;
        std::vector<std::thread> threads;
        for (int i = 0; i < REACTOR_NUM; i++)
        {
            Reactor *reactor_ = new Reactor;
            dispatch.reactor_reg(reactor_);
            reactors.push_back(reactor_);

            std::thread t([reactor_]() {
                reactor_->run();
            });

            threads.push_back(std::move(t));
        }

        dispatch.run([](std::string &&command){
            std::cout << command << "\n";
            return command; 
        });

        for (auto reactor : reactors)
            reactor->stop();

        for (auto &t : threads)
            t.join();

        for (auto reactor : reactors)
            delete reactor;
        
        while (!reactors.empty())
            reactors.pop_back();

        std::cout << "reactor thread joined\n";

        ThreadPool::GetInstance()->stop();
    }

    std::cout << "finish\n";
    return 0;
}